
/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2020原作者。
 *
 *根据Apache许可证2.0版（“许可证”）获得许可；
 *除非符合许可证，否则不得使用此文件。
 *您可以在以下地址获取许可证副本：
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证分发的内容是按“原样”分发的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限和
 *许可证下的限制。
 */

package org.springframework.aop.framework;

import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.Nullable;

/**
 * Class containing static methods used to obtain information about the current AOP invocation.
 *
 * <p>The {@code currentProxy()} method is usable if the AOP framework is configured to
 * expose the current proxy (not the default). It returns the AOP proxy in use. Target objects
 * or advice can use this to make advised calls, in the same way as {@code getEJBObject()}
 * can be used in EJBs. They can also use it to find advice configuration.
 *
 * <p>Spring's AOP framework does not expose proxies by default, as there is a performance cost
 * in doing so.
 *
 * <p>The functionality in this class might be used by a target object that needed access
 * to resources on the invocation. However, this approach should not be used when there is
 * a reasonable alternative, as it makes application code dependent on usage under AOP and
 * the Spring AOP framework in particular.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 13.03.2003
 */
/**
 *类，包含用于获取有关当前AOP调用的信息的静态方法。
 *
 *＜p＞如果AOP框架被配置为
 *公开当前代理（不是默认代理）。它返回使用中的AOP代理。目标对象
 *或advice可以使用它进行建议调用，方法与｛@code getEJBObject（）｝相同
 *可以在EJB中使用。他们还可以使用它来查找建议配置。
 *
 *＜p＞Spring的AOP框架默认情况下不公开代理，因为存在性能成本
 *这样做。
 *
 *＜p＞需要访问的目标对象可能使用该类中的功能
 *到调用上的资源。但是，如果存在
 *一个合理的替代方案，因为它使应用程序代码依赖于AOP和
 *特别是Spring AOP框架。
 *
 *@作者Rod Johnson
 *@作者Juergen Hoeller
 *@自2003年3月13日
 */
public final class AopContext {

	/**
	 * ThreadLocal holder for AOP proxy associated with this thread.
	 * Will contain {@code null} unless the "exposeProxy" property on
	 * the controlling proxy configuration has been set to "true".
	 * @see ProxyConfig#setExposeProxy
	 */
	/**
	 *与此线程关联的AOP代理的ThreadLocal持有者。
	 *将包含｛@code null｝，除非
	 *控制代理配置已设置为“true”。
	 *@参见ProxyConfig#setExposeProxy
	 */
	private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");


	private AopContext() {
	}


	/**
	 * Try to return the current AOP proxy. This method is usable only if the
	 * calling method has been invoked via AOP, and the AOP framework has been set
	 * to expose proxies. Otherwise, this method will throw an IllegalStateException.
	 * @return the current AOP proxy (never returns {@code null})
	 * @throws IllegalStateException if the proxy cannot be found, because the
	 * method was invoked outside an AOP invocation context, or because the
	 * AOP framework has not been configured to expose the proxy
	 */
	/**
	 *尝试返回当前AOP代理。此方法仅在
	 *已经通过AOP调用了调用方法，并且已经设置了AOP框架
	 *以暴露代理。否则，此方法将引发IllegalStateException。
	 *@return当前AOP代理（从不返回｛@code null｝）
	 *如果找不到代理，@throws IllegalStateException，因为
	 *方法是在AOP调用上下文之外调用的，或者因为
	 *AOP框架尚未配置为公开代理
	 */
	public static Object currentProxy() throws IllegalStateException {
		Object proxy = currentProxy.get();
		if (proxy == null) {
			throw new IllegalStateException(
					"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and " +
							"ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.");
		}
		return proxy;
	}

	/**
	 * Make the given proxy available via the {@code currentProxy()} method.
	 * <p>Note that the caller should be careful to keep the old value as appropriate.
	 * @param proxy the proxy to expose (or {@code null} to reset it)
	 * @return the old proxy, which may be {@code null} if none was bound
	 * @see #currentProxy()
	 */
	/**
	 *通过｛@code currentProxy（）｝方法使给定的代理可用。
	 *＜p＞请注意，调用方应小心保持旧值。
	 *@param代理要公开的代理（或｛@code null｝重置它）
	 *@返回旧代理，如果没有绑定，则可能为｛@code null｝
	 *@参见#currentProxy（）
	 */
	@Nullable
	static Object setCurrentProxy(@Nullable Object proxy) {
		Object old = currentProxy.get();
		if (proxy != null) {
			currentProxy.set(proxy);
		}
		else {
			currentProxy.remove();
		}
		return old;
	}

}
